<?php

/**
 * @author littlexiang
 * @package Core
 * @version $Id: Dispatcher.php 685 2009-08-03 06:28:25Z songxiang $
 */
class Core_Dispatcher {

    public static $forward_ct = 0;

    public static function dispatch() {
        Core_Config::init();
        Core_ErrorHandler::init();
        switch (PHP_SAPI) {
            case 'cli':
                self::dispatchCli();
                break;
            default:
                self::dispatchCgi();
                break;
        }
        Core_Context::trigger(Core_Context::AFTER_DISPATCH);
    }

    public static function dispatchCli() {
        try {
            $request = Core_Cli::getInstance();
            $cmd = $request->getCmd();

            $class = 'Task_' . implode('_', array_map('ucfirst', explode('_', $cmd)));
            if (!file_exists(PROJECT_PATH . str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php')) {
                throw new BadMethodCallException('Invalid CMD');
            }
            $app = new $class($request);
            $app->run();
            echo "\nSuccess\n";
        } catch (Exception $e) {
            $log = $e->getMessage();
            $log .= "\n===================================================================================>\n";
            $log .= var_export(Core_Cli::getInstance()->getParams(), true);
            $log .= "\n------------------------------------------------------------------------------------\n";
            $log .= $e->getMessage() . "\n" . $e->getFile() . ' Line ' . $e->getLine() . "\n" . $e->getTraceAsString();
            $log .= "\n<===================================================================================\n\n";
            Core_Log::log($log, 'cliError');
            echo $log;
            echo "\nError\n";
        }
    }

    public static function dispatchCgi($return = false) {
        ob_start();
        try {
            $data = self::runCgi();
            $ret = Core_Vo::render($data);
        } catch (Exception $e) {
            $extras = null;
            if ($e instanceof Core_CatchableException) {
                $code = $e->getCode();
                if ($code > 0) {
                    $real_msg = Core_I18N::_($code, 'error');
                } else {
                    $real_msg = $e->getMessage();
                }
                $log_name = 'userError';
                $extras = $e->extras;
                $ignoreLog = $e->ignoreLog;
            } else {
                $real_msg = Core_Config::get('Core.errorMessage', $e->getMessage());
                $log_name = 'sysError';
                $ignoreLog = false;
            }
            if ($e instanceof BadMethodCallException) {
//            what to do?
            } else {
                if (!$ignoreLog) {
                    $log = "==============================================================>\n";
                    $log .= var_export(Core_Request::getInstance()->getParams(), true) . "\n";
//                $log .= 'raw: ' . file_get_contents('php://input');
                    $log .= "\n------------------------------------------------------------------------------------\n";
                    $log .= $e->getMessage() . "\n" . $e->getFile() . ' Line ' . $e->getLine() . "\n" . $e->getTraceAsString();
                    $log .= "\n<===================================================================================\n\n";

                    Core_Log::log($log, $log_name);
                }
            }
            // android cannot have both msg and obj at the same time
            if ($extras) {
                $ret = array('OK' => (int)$e->getCode(), 'obj' => $extras);
            } else {
                $ret = array('OK' => (int)$e->getCode(), 'msg' => $real_msg);
            }

        }
        Core_Context::$response = $ret;
        if ($ret) {
            if ($ob_length = ob_get_length()) {
                $junk = ob_get_clean(); //drop anything output
                Core_Log::logErr("!something output before json_encode! length: {$ob_length} [{$junk}]");
            }
            $ret = json_encode($ret, JSON_UNESCAPED_UNICODE);
            if ($return) {
                ob_end_clean();
                return $ret;
            }
            echo $ret;
        }
        ob_end_flush();
    }

    public static function runCgi() {
        self::$forward_ct++;
        $request = Core_Request::getInstance();
        $cmd = $request->getCmd();
        $app_dir = defined('APP_DIR') ? APP_DIR : 'App';
        $class = $app_dir . '_' . implode('_', array_map('ucfirst', explode('/', $cmd)));
        if (!file_exists(PROJECT_PATH . str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php')) {
            throw new BadMethodCallException('Invalid CMD', 999999);
        }
        $app = new $class($request);
        return $app->run();
    }

}
